package 基础语法;

import java.util.Arrays;

public class 枚举 {
    public static void main(String[] args) {
        MyEnum myEnum = MyEnum.AA;// AA本质是static修饰的
        System.out.println(myEnum);
        System.out.println(myEnum.name());// 这个显示是其父类Enum的方法
        System.out.println(myEnum.ordinal());// 是在编译器生成的values方法返回的那个数组中的索引

        useEnum(Direction.up);
        useEnum(Direction.right);//只能传入Direction，有限顶，应用场景就是分类。如果是要执行具体计算的全局变量，还得是static修饰具体数据类型

        useStatic(DirectionStatic.up);
        useStatic(1212);// 实际上对于传入的内容没有限定，这样不好
        /*
        * 有 Java 枚举类型（enum）都会自动生成一个 values() 静态方法。
        作用：返回该枚举中定义的所有枚举常量数组。*/
 // 类型推断 var 非常适合 for 循环，JDK 10 引入，JDK 11 改进
        for(var e:MyEnum.values()){
            System.out.println(e);
        }

    }

    static void useEnum(Direction direction) {
        if(direction==Direction.down){//这里又必须使用Direction.down的写法

        }
        switch (direction) {
            case up:// 若将其定义在另一个文件中则用Direction.up=>×，也是用up,可能和Java版本有关
                System.out.println("向上");
                break;
            case down:
                System.out.println("向下");

                break;
            default:
                System.out.println("其他动作");
                break;
        }
    }

    static void useStatic(int direction) {
        switch (direction) {
            case DirectionStatic.up:
                System.out.println("向上");
                break;
            case DirectionStatic.down:
                System.out.println("向下");

                break;
            default:
                System.out.println("其他动作");
                break;
        }
    }

    static void useOther(){
         // ================== 基本用法 ==================
        // 枚举常量直接使用
        Status s1 = Status.NEW;
        System.out.println("枚举常量: " + s1); // 输出 NEW(0, 新建状态, N)

        // 遍历所有枚举
        System.out.println("所有枚举: " + Arrays.toString(Status.values()));

        // 获取枚举的 name 和 ordinal
        System.out.println("名称: " + s1.name() + ", 序号: " + s1.ordinal());

        // ================== 带属性的用法 ==================
        System.out.println("code=" + s1.getCode());
        System.out.println("desc=" + s1.getDesc());
        System.out.println("shortName=" + s1.getShortName());

        // 通过 code 获取枚举
        Status s2 = Status.fromCode(2);
        System.out.println("通过 code=2 获取枚举: " + s2);

    }
}

enum Direction {
    up, down, left, right;

}

class DirectionStatic {
    public static final int up = 0;
    public static final int down = 1;
    public static final int left = 2;
    public static final int right = 2;

}

enum MyEnum {
    // 枚举类的第一行，只能罗列枚举对象的名称，这些名称本质是常量
    // 可以先编译，然后反编译生成的.class文件，看一下这里真正的代码
    // 编译： javac -encoding UTF-8 枚举.java，会产生两个class字节码文件，枚举.class和 MyEnum.class
    // 反编译MyEnum.class：javap MyEnum.class
    // 结果如下：
    /**
     * final class 基础语法.MyEnum extends java.lang.Enum<基础语法.MyEnum> {
     * public static final 基础语法.MyEnum AA;
     * public static final 基础语法.MyEnum BB;
     * public static final 基础语法.MyEnum C;
     * public static final 基础语法.MyEnum D;
     * public static 基础语法.MyEnum[] values();//可以直接使用，
     * public static 基础语法.MyEnum valueOf(java.lang.String);
     * static {};
     * }
     * 枚举本质是一个final的类，继承自Enum
     * 可见枚举中的属性本质就是一个常量且是其自身的类型
     * 编译器还为其新增了几个方法
     * 
     * 接口也可也用类似的方法看源码
     * 感觉就是封装了几个 static修饰的常量，自己也可也做类似的。
     */

    AA, BB, C, D;
    
    // LL;不能写
}
  /**
     * 定义一个带属性和方法的枚举
     * 每个枚举值有三个字段：code、desc、shortName
     */
    public enum Status {
        //枚举值，写在第一行逗号分隔
        NEW(0, "新建状态", "N"),//按反编译结果，这就是调用构造器，因此必须提供一个对应构造器
        PROCESSING(1, "处理中", "P"),
        SUCCESS(2, "成功完成", "S"),
        FAILED(3, "执行失败", "F");


        private final int code;       // 编码
        private final String desc;    // 描述
        private final String shortName; // 简称

        // 构造方法（必须是 private）
        Status(int code, String desc, String shortName) {
            this.code = code;
            this.desc = desc;
            this.shortName = shortName;
        }

        // Getter 方法
        public int getCode() {
            return code;
        }

        public String getDesc() {
            return desc;
        }

        public String getShortName() {
            return shortName;
        }

        // 通过 code 获取枚举实例
        public static Status fromCode(int code) {
            for (Status s : Status.values()) {//values是虚拟机给加上的属性，反编译可以看到
                if (s.code == code) return s;
            }
            throw new IllegalArgumentException("未知 code: " + code);
        }

        // 重写 toString()，方便打印
        @Override
        public String toString() {
            return name() + "(" + code + ", " + desc + ", " + shortName + ")";
        }
    }
